import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model, ObjectId } from 'mongoose';
import { CreateGameDto } from './dto/create-game.dto';
import { Game, GameDocument } from './schemas/game.schema';
import * as dayjs from 'dayjs';
import * as utc from 'dayjs/plugin/utc';
import * as isBetween from 'dayjs/plugin/isBetween';
import 'dayjs/locale/zh-cn';
import { EveryDayIs, EveryDayIsDocument } from './schemas/every-day-is.schema';

dayjs.locale('zh-cn');
dayjs.extend(utc);
dayjs.extend(isBetween);

@Injectable()
export class GamesService {
  constructor(
    @InjectModel(Game.name) private gameModel: Model<GameDocument>,
    @InjectModel(EveryDayIs.name)
    private everyDayIsModel: Model<EveryDayIsDocument>,
  ) {}

  /**
   * 创建一场游戏
   * @param createGameDto 要创建的游戏
   * @returns 创建好的游戏
   */
  create(createGameDto: CreateGameDto): Promise<GameDocument> {
    const createdGame = new this.gameModel(createGameDto);
    let date = dayjs.utc(createdGame.firstDayOpenTime);

    // 生成每一天游戏的初始记录
    createdGame.everyDayIs = new Map<string, EveryDayIsDocument>();
    for (let index = 0; index < createdGame.days; index++) {
      const createdEveryDayIs = new this.everyDayIsModel();
      const key = date.format('YYYY-MM-DD');

      date = date.add(1, 'd');
      createdGame.everyDayIs.set(key, createdEveryDayIs);
    }

    return createdGame.save();
  }

  /**
   * 查询已经开始的一场游戏
   * @returns 已经开始的一场游戏
   */
  findStarted(): Promise<GameDocument> {
    return this.gameModel.findOne({ isOver: false }, '-__v').exec();
  }

  /**
   * 查询所有游戏
   * @returns 所有游戏
   */
  async findAll(): Promise<Game[]> {
    return this.gameModel.find({}, '').exec();
  }

  /**
   * 是不是游戏加入阶段
   * @param gameDocument 游戏文档
   * @returns 是否是加入阶段
   */
  isJoinStage(gameDocument: GameDocument): boolean {
    const now = dayjs.utc();
    return now.isBefore(gameDocument.firstDayOpenTime);
  }

  /**
   * 加入游戏
   * @param userId 用户标识
   */
  join(userId: string) {
    return this.gameModel.updateOne(
      { isOver: false, users: { $ne: userId } },
      { $push: { users: userId } },
    );
  }

  /**
   * 判断用户有没有加入游戏
   * @param gameDocument 游戏文档
   * @param userId 用户标识
   */
  hasJoined(gameDocument: GameDocument, userId: string): boolean {
    const { users } = gameDocument;
    return users.toString().split(',').includes(userId);
  }

  /**
   * 判断现在是不是猜涨跌的时间
   */
  inGuessRiseFallTime(): boolean {
    const now = dayjs.utc();
    const openTime = now.startOf('d').add(1, 'h').add(30, 'm').add(-1, 's');
    const endTime = openTime.add(3, 'h').add(30, 'm').add(2, 's');
    return now.isBetween(openTime, endTime);
  }

  /**
   * 删除所有游戏
   */
  deleteAll() {
    return this.gameModel.deleteMany();
  }

  /**
   * 猜涨跌
   * @param gameDocument 游戏文档
   * @param userId 用户标识
   * @param isRise 是否涨
   * @returns 保存后的游戏文档
   */
  guessRiseFall(gameDocument: GameDocument, userId: string, isRise: boolean) {
    const key = dayjs.utc().format('YYYY-MM-DD');
    const everyDayIsDocument = gameDocument.everyDayIs.get(key);

    if (isRise) {
      everyDayIsDocument.guessRise.push((userId as unknown) as ObjectId);
    } else {
      everyDayIsDocument.guessFall.push((userId as unknown) as ObjectId);
    }

    return gameDocument.save();
  }
}
